package com.atguigu.url.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

/**
 * @version V1.0
 * @author: realife_cheng
 * @date: 2019/12/13 23:55
 * @description:
 */
@Slf4j
@Component
public class HttpUtils {
    @Autowired
    private PoolingHttpClientConnectionManager cm;
    @Autowired
    private MD5DigestUtil md5DigestUtil;
    @Autowired
    private StringRedisTemplate redisTemplate;


    private static List<String> userAgentList = null;

    //静态代码块会在类被加载的时候执行
    static {
        userAgentList = new ArrayList<String>();
        userAgentList.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36");
        userAgentList.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:73.0) Gecko/20100101 Firefox/73.0");
        userAgentList.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15");
        userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299");
        userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");
        userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0");
        userAgentList.add("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
        userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36");
        userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0");
        userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 Edg/95.0.1020.53");
    }


    /**
     * 根据请求地址下载数据
     *
     * @param url
     * @return 页面数据
     */
    public String doGetHtml(String url) {
        //获取HttpClient对象
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(this.cm).build();
        //创建httpGet请求对象，设置URL
        HttpGet httpGet = new HttpGet(url);

        //伪装成浏览器的请求
        httpGet.setHeader("User-Agent",
                "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");

        //配置请求
        httpGet.setConfig(this.getConfig());

        CloseableHttpResponse response = null;

        try {
            //使用HTTPClient发起请求，获取响应
            response = httpClient.execute(httpGet);
            //解析响应，返回结果
            if (response.getStatusLine().getStatusCode() == 200) {
                //判断响应体Entity是否不为空，如果不为空就可以使用entityUtils
                if (null != response.getEntity()) {
                    String content = EntityUtils.toString(response.getEntity(), "utf8");
                    return content;
                }
            }
        } catch (Exception e) {
            log.info("[**网页数据获取失败,{}**]", e.getMessage());
        } finally {
            //释放资源
            ResourcesCloseUtils.close(response);
        }

        return "没有获取到网页内容";
    }


    /**
     * 下载图片
     *
     * @param url
     * @return 图片名称
     */
    public String doGetImage(String url) {
        //获取HttpClient对象
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(this.cm).build();
        //创建httpGet请求对象，设置URL
        HttpGet httpGet = new HttpGet(url);

        //伪装成浏览器的请求
        httpGet.setHeader("User-Agent",
                "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");

        //设置请求信息
        httpGet.setConfig(this.getConfig());

        CloseableHttpResponse response = null;

        try {
            //使用HTTPClient发起请求，获取响应
            response = httpClient.execute(httpGet);
            //解析响应，返回结果
            if (response.getStatusLine().getStatusCode() == 200) {
                //判断响应体Entity是否不为空，如果不为空就可以使用entityUtils
                if (null != response.getEntity()) {
                    //下载图片
                    //获取图片后缀
                    String extName = url.substring(url.lastIndexOf("."));
                    //创建图片名
                    String picName = UUID.randomUUID().toString().replace("-", "") + extName;
                    //下载图片
                    OutputStream outputStream = new FileOutputStream(new File("D:\\testarea\\IOTest\\weiboimages\\" + picName));
                    response.getEntity().writeTo(outputStream);
                    //返回图片名称
                    return picName;
                }
            }
        } catch (Exception e) {
            log.info("[**网页数据获取失败,{}**]", e.getMessage());
        } finally {
            //释放资源
            ResourcesCloseUtils.close(response);
        }

        return "没有获取到图片名称";
    }


    /**
     * get douyin video
     *
     * @param url
     * @return
     */
    public void doGetVideo(String url, String dstPath) {
        long start = System.currentTimeMillis();
        System.out.println(" 执行 ==> doGetVideo(String url, String dstPath) ");
        StringBuilder tag = new StringBuilder("进入doGetVideo->");

        //获取HttpClient对象
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(this.cm).build();

        String urlMd5 = md5DigestUtil.getMD5(url);
        String str = redisTemplate.opsForValue().get(urlMd5);
        String[] kArr = str.split("_");
        String key0 = kArr[0];
        String val1 = kArr[1];
        System.out.println("<< redis key0 = " + key0 + ", redis val1 = " + val1 + " >>");
        //创建图片名
        String picName = urlMd5 + ".mp4";

        //满足条件就提交给线程池干活
        if (val1.equalsIgnoreCase("0")) {
            tag.append("0没有下载过->");

            //创建httpGet请求对象，设置URL
            HttpGet httpGet = new HttpGet(url);
            //伪装成浏览器的请求
            httpGet.setHeader("User-Agent", userAgentList.get(new Random().nextInt(userAgentList.size())));
            //设置请求信息
            httpGet.setConfig(this.getConfig());
            CloseableHttpResponse response1 = null;
            try {
                //使用HTTPClient发起请求，获取响应
                response1 = httpClient.execute(httpGet);
                int statusCode = response1.getStatusLine().getStatusCode();
                //解析响应，返回结果
                if (statusCode == 200) {
                    tag.append("statusCode=200->");
                    //判断响应体Entity是否不为空，如果不为空就可以使用entityUtils
                    if (null != response1.getEntity()) {
                        tag.append("saveVideoToLocal->");
                        //下载图片 D:\testarea\douyin\qiongqiong\
                        OutputStream outputStream = new FileOutputStream(new File(dstPath + picName));
                        //key_tag  tag=0 表示没有下载过
                        response1.getEntity().writeTo(outputStream);
                        //下载完成后 tag+1
                        String val = urlMd5 + "_" + "2xx";
                        redisTemplate.opsForValue().set(urlMd5, val);
                        tag.append("updateRedisTag2xxOk->");
                    }
                } else {
                    tag.append("statusCode=4xx->");
                    //服务器访问异常 可能403被拒绝服务 tag+1
                    String val = urlMd5 + "_" + "4xx";
                    redisTemplate.opsForValue().set(urlMd5, val);
                    tag.append("updateRedisTag4xxOk->");
                }

            } catch (IOException e) {
                System.out.println(e.getMessage());
                tag.append("catch->");
            } finally {
                tag.append("finally");
                ResourcesCloseUtils.close(response1);
            }
        } else {
            //可能成功处理2xx, 可能网站拒绝服务4xx
            tag.append("已经处理过该url~");
        }

        long end = System.currentTimeMillis();
        long downAndSaveTime = end - start;
        System.out.println("一次下载存储消耗时间= " + downAndSaveTime + " 毫秒, tag= " + tag.toString());
        redisTemplate.opsForValue().set("time" + urlMd5, downAndSaveTime + "");
    }


    /**
     * 设置请求信息
     *
     * @return
     */
    private RequestConfig getConfig() {
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(1000000)
                .setConnectionRequestTimeout(5000000)
                .setSocketTimeout(1000000)
                .build();

        return config;
    }

}
